package com.body.park.user.bloom;

import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.List;

/**
 * @Author chaoxian.wu
 * @DATE 2022/4/20 19:40
 * redis操作布隆过滤器
 */
@Component
public class RedisBloomFilter {

    @Resource
    private RedisTemplate redisTemplate;

    /**
     * 删除缓存的key
     *
     * @param key 需要删除的key
     */
    public void delete(String key) {
        redisTemplate.delete(key);
    }

    /**
     * 将值在布隆过滤器中添加映射关系
     * 一个一个元素添加时使用
     *
     * @param bloomFilterHelper 布隆过滤器对象
     * @param key key
     * @param value value
     * @param <T> 泛型
     */
    public <T> void add(BloomFilterHelper<T> bloomFilterHelper, String key, T value) {
        int[] offsetArray = bloomFilterHelper.offsetArray(value);
        for (int offset : offsetArray) {
            //setBit命令；
            redisTemplate.opsForValue().setBit(key, offset, true);
        }
    }

    /**
     * 在布隆过滤器中添加值
     *
     * @param bloomFilterHelper 布隆过滤器
     * @param key key
     * @param valueList 值的集合
     * @param <T> 泛型
     */
    public <T> void addList(BloomFilterHelper<T> bloomFilterHelper, String key, List<T> valueList) {
        redisTemplate.executePipelined(new RedisCallback<Long>() {
            @Override
            public Long doInRedis(RedisConnection redisConnection) throws DataAccessException {
                //开启连接
                redisConnection.openPipeline();
                for (T value : valueList) {
                    //hash计算
                    int[] offsetArray = bloomFilterHelper.offsetArray(value);
                    for (int offset : offsetArray) {
                        redisConnection.setBit(key.getBytes(), offset, true);
                    }
                }
                redisConnection.close();
                return null;
            }
        });
    }

    /**
     * 判断值是否存在
     *
     * @param bloomFilterHelper 布隆过滤器
     * @param key key
     * @param value 值
     * @param <T> 泛型
     * @return
     */
    public <T> boolean isExists(BloomFilterHelper<T> bloomFilterHelper, String key, T value) {
        int[] offsetArray = bloomFilterHelper.offsetArray(value);
        for (int offset : offsetArray) {
            //判断bit位的值是否为1，
            if (!redisTemplate.opsForValue().getBit(key, offset)) {
                return false;
            }
        }
        return true;
    }
}
